package com.csjbot.snowbot_rogue.platform;

import android.content.Context;
import android.graphics.PointF;

import com.android.core.entry.Static;
import com.android.core.util.SharedUtil;
import com.csjbot.csjbase.event.IBus;
import com.csjbot.csjbase.log.Csjlogger;
import com.csjbot.snowbot_rogue.Events.AIUIEvent;
import com.csjbot.snowbot_rogue.Events.EventsConstants;
import com.csjbot.snowbot_rogue.Events.HWTestEvent;
import com.csjbot.snowbot_rogue.R;
import com.csjbot.snowbot_rogue.servers.serials.SelfCheckParser;
import com.csjbot.snowbot_rogue.servers.serials.SnowBotAction;
import com.csjbot.snowbot_rogue.servers.serials.SnowBotSerialListener;
import com.csjbot.snowbot_rogue.servers.serials.SnowBotSerialServer;
import com.csjbot.snowbot_rogue.servers.slams.MoveServerMapListener;
import com.csjbot.snowbot_rogue.servers.slams.SnowBotMoveServer;
import com.csjbot.snowbot_rogue.servers.slams.events.RobotStatusUpdateEvent;
import com.csjbot.snowbot_rogue.utils.CSJToast;
import com.csjbot.snowbot_rogue.utils.Constant;
import com.slamtec.slamware.action.MoveDirection;
import com.slamtec.slamware.robot.Location;
import com.slamtec.slamware.robot.Pose;
import com.upcontrol.uartagent.entity.SNGetPacket;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

import dou.utils.StringUtils;


/**
 * Created by Administrator on 2016/9/13 0013.
 */
public class SnowBotManager implements SnowBotAction {
    private volatile static SnowBotManager ourInstance;

    // 所有的数据的有效期是300秒
    private static int TmeToLive = 300;

    private SnowBotState state = new SnowBotState();
    private String UpBodySN, downBodySN;

    // 每30分钟获取一次传感器数据
    private ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
    private SnowBotListener listener = null;
    private SnowBotMoveServer moveServer = SnowBotMoveServer.getInstance();
    private SnowBotSerialServer snowBotAction = SnowBotSerialServer.getOurInstance();

    private int getCount = 0;
    private static final int CHECK_COUNT = 2;
    private EventBus mIbus = null;

    private boolean isCharging = false;
    private int powerPercent = 0;
    private boolean isPartol = false;
    private boolean lowPowerDetected = false;


    public boolean isSlamConnected() {
        return moveServer.isSlamConnected();
    }


    public void close() {
        scheduledThreadPool.shutdown();
    }

    /**
     * 在屏幕上选择一个点，让机器人走过去
     *
     * @param offsetX 选择的点的x坐标
     * @param offsetY 选择的点的y坐标
     */
    public void moveTo(float offsetX, float offsetY) {
        moveServer.moveTo(offsetX, offsetY);
    }

    /**
     * 在屏幕上添加虚拟墙
     *
     * @param startP 起始点
     * @param endP   终点
     */
    public void addWall(PointF startP, PointF endP) {
        moveServer.addWall(startP, endP);
    }

    /**
     * 获取机器人的当前姿态
     *
     * @return 机器人的当前姿态
     */
    public Pose getPose() {
        return moveServer.getPose();
    }

    /**
     * 获取机器人的当前姿态
     *
     * @return 机器人的当前姿态
     */
    public Pose getCurrentPose() {
        return moveServer.getCurrentPose();
    }

    public int getShowMapH() {
        return moveServer.getShowMapH();
    }

    /**
     * 回去充电
     */
    public void goHome() {
        moveServer.goHome();
    }

    /**
     * 取消所有的动作
     */
    public void cancelAction() {
        moveServer.cancelAction();
    }

    /**
     * 运动到实际地图上的某个点
     *
     * @param location 地图上的点
     */
    public void moveTo(Location location) {
        moveServer.moveTo(location);
    }


    /**
     * 清除地图
     */
    public void clearMap() {
        moveServer.clearMap();
    }

    /**
     * 清除所有的虚拟墙
     */
    public void clearWalls() {
        moveServer.clearWalls();
    }

    public void setMoveServerMapListener(MoveServerMapListener listener) {
        moveServer.setMoveServerMapListener(listener);
    }


    public void setWakeupMapUpdate(boolean pauseUpdateMap) {
        moveServer.setWakeupMapUpdate(pauseUpdateMap);
    }

    /**
     * 连接底盘
     */
    public void connect() {
        moveServer.connect();
    }

    /**
     * 开始获取地图
     *
     * @param context 上下文
     */
    public void getMap(final Context context) {
        moveServer.getMap(context, null);
    }

    /**
     * 开始获取地图
     *
     * @param context 上下文
     */
    public void getMap(final Context context, MoveServerMapListener listener) {
        moveServer.getMap(context, listener);
    }

    /**
     * 停止获取地图
     */
    public void stopGetMap() {
        moveServer.stopGetMap();
    }

    /**
     * 开始巡逻
     *
     * @param poseList 所有需要巡逻的点
     */
    public void partol(List<Pose> poseList) {
        isPartol = true;
        moveServer.partol(poseList);
    }
    public void partol(List<Pose> poseList,int count) {
        isPartol = true;
        moveServer.partol(poseList,count);
    }

    /**
     * 停止巡逻
     */
    public void stopPartol() {
        isPartol = false;
        moveServer.stopPartol();
    }

    public void fakeWakeup() {
        moveServer.fakeWakeup();
    }

    public void configNetWork(final String ssid, final String passwd, final SnowBotNetwokListen listen) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (listen != null) {
                    listen.configWifiState(moveServer.connectWifi(ssid, passwd));
                }
            }
        }).start();
    }

    public void configNetWorkNew(final SnowBotNetwokListen listen) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (listen != null) {
                    listen.configWifiState(moveServer.connectWifiNew());
                }
            }
        }).start();
    }

    /**
     * 获取网络状态
     *
     * @param listen 获取网络状态的监听器
     */
    public void getNetworkStatus(final SnowBotNetwokListen listen) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (listen != null) {
                    listen.getWifiStatus(moveServer.getNetworkStatus());
                }
            }
        }).start();
    }


    /**
     * 控制小雪人转身
     *
     * @param degree 以机器人朝向为基准，正数逆时针转，负数顺时针转（正数向左转，负数向右转）
     */
    public void turnRound(final short degree) {
        moveServer.turnRound(degree);
    }

    public String getUpBodySN() {
        return UpBodySN;
    }

    public String getDownBodySN() {
        return downBodySN;
    }

    public boolean isCharging() {
        return isCharging;
    }

    public int getPowerPercent() {
        return powerPercent;
    }

    public void setAutoUpdateMap(boolean b) {
        moveServer.setAutoUpdateMap(b);
    }

    public boolean isPartol() {
        return isPartol;
    }

    public boolean isLowPowerDetected() {
        return lowPowerDetected;
    }

    public class SnowBotState {
        boolean isCharging = false;
        int power;
        int pm25;
        int temperature;
        int humidity;
    }

    public SnowBotState getSnowBotState() {
        snowBotAction.requireAllSensor();
        getCount = 0;
        return state;
    }


    public static SnowBotManager getInstance() {
        if (ourInstance == null) {
            ourInstance = new SnowBotManager();
        }

        return ourInstance;
    }

    public void postEvent(IBus.IEvent event) {
        if (mIbus != null) {
            Csjlogger.debug("postEvent " + event.getTag());
            mIbus.post(event);
        }
    }

    public void setSnowBotListener(SnowBotListener listener) {
        this.listener = listener;
    }

    private SnowBotManager() {
        Csjlogger.info("SnowBotManager init");
        mIbus = EventBus.getDefault();
        mIbus.register(this);
        snowBotAction.setBotListener(new SnowBotSerialListener() {

            @Override
            public void touchedGet() {
                postEvent(new AIUIEvent(EventsConstants.AIUIEvents.AIUI_EVENT_TOUCH_GET));
                Csjlogger.info("触摸传感器信号");
            }

            @Override
            public void temperature_humidityGet(int humidity, int temperature) {
                state.humidity = humidity;
                state.temperature = temperature;
                getCount++;
                if (getCount == CHECK_COUNT) {
                    if (listener != null) {
                        listener.stateChange(state);
                    }
                    getCount = 0;
                }
            }

            @Override
            public void combustiblegasGet() {

            }

            @Override
            public void PM25Get(short pm25) {
                state.pm25 = pm25;
                getCount++;
                if (getCount == CHECK_COUNT) {
                    if (listener != null) {
                        listener.stateChange(state);
                    }
                    getCount = 0;
                }
            }

            @Override
            public void UpBodySNGet(String SN) {
                Csjlogger.info("获取到机器人SN {}", SN);
                UpBodySN = SN;
            }

            @Override
            public void DownBodySNGet(String SN) {
                Csjlogger.info("获取到机器人下身板SN {}", SN);
                downBodySN = SN;
            }


            @Override
            public void faultyGet(int errorType, int errorCode) {

            }

            @Override
            public void snowBotOff() {

            }

            @Override
            public void upBodySelfChecked(int status) {
                Csjlogger.debug("upBodySelfChecked is {}", status);
                postEvent(new HWTestEvent("上身板检测信息 "
                        + StringUtils.formatJson(SelfCheckParser.checkToString(SelfCheckParser.letHumanReadAbleUpBodyCheck(status)))));
            }

            @Override
            public void downBodySelfChecked(int status) {
                Csjlogger.debug("downBodySelfChecked is {}", status);
                postEvent(new HWTestEvent("下身板检测信息 "
                        + StringUtils.formatJson(SelfCheckParser.checkToString(SelfCheckParser.letHumanReadAbleDownBodyCheck(status)))));
            }

            @Override
            public void sendSuccess() {
//                localBroadcastManager.sendBroadcast(new Intent(Constant.ACTION_SERIAL_SEND_OK));
                postEvent(new AIUIEvent(EventsConstants.SerialportEvents.ACTION_SERIAL_SEND_OK));
            }
        });

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (!isSNValid(UpBodySN) && !isSNValid(downBodySN)) {
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    snowBotAction.getRobotSN();
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    snowBotAction.getRobotDownSN();
                }
            }
        }).start();

    }

    /**
     * 检查是否是合格的SN
     *
     * @param sn 测试的SN
     * @return 如果SN 不为空 并且不为 全0，就是合法的SN，反之是不合法的SN
     */
    private boolean isSNValid(String sn) {
        return !StringUtils.isEmpty(sn) && !sn.equals(SNGetPacket.SN_ERROR);
    }


    public void moveBy(MoveDirection direction) {
        if (moveServer != null) {
            moveServer.moveBy(direction);
        }
    }

    /**
     * 左手臂摆动
     * <p/>
     * 数据格式：0xAA    0x12    0x80    0x02    0x01    number  check
     *
     * @param number 手臂摆动次数
     */
    @Override
    public void swingLeftArm(byte number) {
        snowBotAction.swingLeftArm(number);
    }

    /**
     * 右手臂摆动
     * <p/>
     * 数据格式：0xAA    0x12    0x80    0x03    0x01    number  check
     *
     * @param number 手臂摆动次数
     */
    @Override
    public void swingRightArm(byte number) {
        snowBotAction.swingRightArm(number);
    }

    /**
     * 双臂摆动
     * <p/>
     * 数据格式：0xAA    0x12    0x80    0x04    0x01    number  check
     *
     * @param number 手臂摆动次数
     */
    @Override
    public void swingDoubleArm(byte number) {
        snowBotAction.swingDoubleArm(number);
    }


    /**
     * 开启传感器
     * <p/>
     * 数据格式： 0xAA   0x12    0x80    0x07    0x01    sensorType  check
     *
     * @param sensorType 传感器类型
     */
    @Override
    public void turnOnSensor(byte sensorType) {

    }

    /**
     * 关闭传感器
     * <p/>
     * 数据格式： 0xAA   0x12    0x80    0x08    0x01    sensorType  check
     *
     * @param sensorType 传感器类型
     */
    @Override
    public void turnOffSensor(byte sensorType) {

    }

    public int getErrorCount(){
        return moveServer.getErrorCount();
    }

    /**
     * 数据开始发送
     * <p/>
     * 数据格式： 0xAA   0x12    0x80    0x09    0x01   sensorType  check
     *
     * @param sensorType 传感器类型
     *                   0x02   温湿度
     *                   0x04   pm2.5
     *                   0x05   电量
     */
    @Override
    public void requireSend(byte sensorType) {

    }

    /**
     * 所有的传感器数据开始发送
     * <p/>
     * 数据格式： 0xAA   0x12    0x80    0x09    0x01    sensorType  check
     */
    @Override
    public void requireAllSensor() {

    }


    /**
     * 获取机器人的SN
     * <p/>
     * 数据格式： 0xAA   0x12    0x80    0x0B    0x00   (无数据)   0x47
     */
    @Override
    public void getRobotSN() {
        snowBotAction.getRobotSN();
    }

    @Override
    public void snowBotOff() {
        snowBotAction.snowBotOff();
    }

    @Override
    public void getRobotDownSN() {
        snowBotAction.getRobotDownSN();
    }

    @Override
    public void requireSelfCheck() {
        snowBotAction.requireSelfCheck();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void defaultEvent(AIUIEvent event) {

    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void robotStatusUpdated(RobotStatusUpdateEvent event) {
        isCharging = event.isCharging();
        powerPercent = event.getBatteryPercentage();

        // 当不再充电并且 电量小于 Constant.LOW_POWER_GO_HOME(30)
        if (powerPercent < Constant.LOW_POWER_GO_HOME && !isCharging) {
            lowPowerDetected = true;
            Csjlogger.info("low power detected");
        }


        // 当检测到充电，lowPowerDetected = false
        if (isCharging) {
            lowPowerDetected = false;
        }
    }

}
